#include "hj212_request.h"
#include "hj212_msg.h"
#include "hj212_pack.h"
#include "hj212_client.h"
#include "hj212_request/hj212_base_request.h"

const static hj212_request_match request_table[] =
{
    hj212_request_1000_match,
    hj212_request_1011_match,
    hj212_request_1012_match,
    hj212_request_2011_match,
    hj212_request_2012_match,
    hj212_data_request_match,
};

int hj212_request_parse(struct hj212_client *client, struct hj212_generalmsg *msg, uint32_t package_state)
{
    int result = -1;

    for (int i = 0; i < sizeof(request_table) / sizeof(request_table[0]); i++)
    {
        if (request_table[i])
        {
            result = request_table[i](client, msg, package_state);
            if (!result)
            {
                // 有请求匹配成功时直接退出
                break;
            }
        }
    }
    return result;
}

void hj212_request_handle(struct hj212_client *client, struct hj212_request *request)
{
    if (request->handle)
    {
        request->handle(client, request);
    }
    else
    {
        hj212_commit_request_result(client, REQUEST_EXE_RESULT_NODATA, request);
        rt_list_remove(&request->list);
    }
}

void hj212_request_init(struct hj212_request *request,
                        const char *qn,
                        int cn,
                        request_handle_t handle,
                        struct hj212_client *client)
{
    strncpy(request->qn, qn, HJ212_QN_MAX_LEN);
    request->handle = handle;
    request->cn = cn;
    rt_list_init(&request->list);
    rt_list_insert_before(&client->request_list, &request->list);
}

void hj212_request_destroy(struct hj212_request *request)
{
    rt_list_remove(&request->list);
}

int hj212_send_request_response(struct hj212_client *client,
                                enum request_response respcode,
                                const char *qn)
{
    return hj212_send_local_pack(client, qn, "91", 9011, 0, NULL, "QnRtn=%d;", (int)respcode);
}

int hj212_send_request_exe_result(struct hj212_client *client,
                                  enum request_exe_result resultcode,
                                  const char *qn)
{
    return hj212_send_local_pack(client, qn, "91", 9012, 0, NULL, "ExeRtn=%d;", (int)resultcode);
}


/* 提交执行结果 (回复并产生事件)(用于未创建request的场景) */
int hj212_commit_request_result_frommsg(struct hj212_client *client,
                                        enum request_exe_result resultcode,
                                        struct hj212_generalmsg *msg)
{
    /* 生成请求事件 */
    struct hj212_request_event event;
    event.cn = msg->parent.cn;
    event.error_code = resultcode;
    event.parent.timestamp = hj212_client_current_timestamp(client);
    if (resultcode == REQUEST_EXE_RESULT_SUCCEED)
        event.parent.type = HJ_EVENT_REQUEST_SUCCESS;
    else
        event.parent.type = HJ_EVENT_REQUEST_FAILED;
    hj212_client_event_push(client, &event.parent);

    return hj212_send_request_exe_result(client, resultcode, msg->parent.qn);
}

/* 提交执行结果 (回复并产生事件)(用于已创建request的场景) */
int hj212_commit_request_result(struct hj212_client *client,
                                enum request_exe_result resultcode,
                                struct hj212_request *request)
{
    /* 生成请求事件 */
    struct hj212_request_event event;
    event.cn = request->cn;
    event.error_code = resultcode;
    event.parent.timestamp = hj212_client_current_timestamp(client);
    if (resultcode == REQUEST_EXE_RESULT_SUCCEED)
        event.parent.type = HJ_EVENT_REQUEST_SUCCESS;
    else
        event.parent.type = HJ_EVENT_REQUEST_FAILED;
    hj212_client_event_push(client, &event.parent);

    return hj212_send_request_exe_result(client, resultcode, request->qn);
}


enum request_response hj212_check_request_msg(struct hj212_client *client, struct hj212_generalmsg *msg, uint32_t package_state)
{
    if (package_state & UNPACK_NO_MN)       // MN
        return REQUEST_RESPONSE_MN_ERROR;

    if (package_state & UNPACK_NO_PW)       // PW
        return REQUEST_RESPONSE_PW_ERROR;

    if (package_state & UNPACK_NO_ST)       // ST
        return REQUEST_RESPONSE_ST_ERROR;

    if (package_state & UNPACK_NO_CN)       // CN
        return REQUEST_RESPONSE_CN_ERROR;

    if (package_state & (UNPACK_CRC_ERROR | UNPACK_LEN_ERROR))  // 长度错或者CRC错
        return REQUEST_RESPONSE_CRC_ERROR;

    if (package_state & UNPACK_NO_FLAG)       // FLAG
        return REQUEST_RESPONSE_FLAG_ERROR;

    char tmp_string[40];

    /* MN */
    if (hj212_client_command(client, GET_HJ212_CLIENT_MN, tmp_string) < 0)
        return REQUEST_RESPONSE_UNKNOWN_ERROR;
    if (strcmp(msg->parent.mn, tmp_string))
        return REQUEST_RESPONSE_MN_ERROR;

    /* PWD */
    if (hj212_client_command(client, GET_HJ212_ACCESS_PWD, tmp_string) < 0)
        return REQUEST_RESPONSE_UNKNOWN_ERROR;
    if (strcmp(msg->parent.access_pwd, tmp_string))
        return REQUEST_RESPONSE_PW_ERROR;

    /* ST */
    if (hj212_client_command(client, GET_HJ212_SYS_CODE, tmp_string) < 0)
        return REQUEST_RESPONSE_UNKNOWN_ERROR;
    if (strcmp(msg->parent.st, tmp_string))
        return REQUEST_RESPONSE_ST_ERROR;

    /* CN */
    if (msg->parent.cn < 1000 || msg->parent.cn >= 10000)
        return REQUEST_RESPONSE_CN_ERROR;

    /* Flag */
    int protocol;
    if (hj212_client_command(client, GET_HJ212_PROTOCOL, &protocol) < 0)
        return REQUEST_RESPONSE_UNKNOWN_ERROR;
    int flag = (protocol == HJ212_PROTOCOL_2017 ?
                HJ_FLAG_HJ212_2017 : HJ_FLAG_HJ212_2005) |
               HJ_FLAG_NEED_RESPONSE;
    if (msg->parent.flag != flag)
        return REQUEST_RESPONSE_FLAG_ERROR;

    return REQUEST_RESPONSE_ACCEPT;
}

int hj212_standard_request_preprocessing(struct hj212_client *client, struct hj212_generalmsg *msg, uint32_t package_state, int cn)
{
    if (msg->parent.cn != cn)
    {
        return -1;  // 拒绝处理
    }
    /* 捕捉到上位机的请求 */
    enum request_response response = hj212_check_request_msg(client, msg, package_state);

    /* 回复上位机 */
    hj212_send_request_response(client, response, msg->parent.qn);

    /* 生成请求事件 */
    struct hj212_request_event event;
    event.cn = cn;
    event.error_code = response;
    event.parent.timestamp = hj212_client_current_timestamp(client);
    if (response == REQUEST_RESPONSE_ACCEPT)
        event.parent.type = HJ_EVENT_REQUEST;
    else
        event.parent.type = HJ_EVENT_INVALID_REQUEST;
    hj212_client_event_push(client, &event.parent);

    if (response != REQUEST_RESPONSE_ACCEPT)
        return 1;   // 已处理，不需要执行请求
    else
        return 0;   // 已处理, 可以继续执行请求
}

